package com.foreveross.crawl.adapter.sub.impl20140402.v3;

import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.Source;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.MessageConstraintException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

import com.foreveross.crawl.adapter.AbstractAdapter;
import com.foreveross.crawl.adapter.PlaneInfoEntityBuilder;
import com.foreveross.crawl.common.exception.self.PageErrorResultException;
import com.foreveross.crawl.common.util.RegHtmlUtil;
import com.foreveross.crawl.domain.airfreight.AbstractPlaneInfoEntity;
import com.foreveross.crawl.domain.airfreight.CabinEntity;
import com.foreveross.crawl.domain.airfreight.doub.ReturnCabinEntity;
import com.foreveross.crawl.domain.airfreight.doub.ReturnDoublePlaneInfoEntity;
import com.foreveross.crawl.exception.FlightInfoNotFoundException;
import com.foreveross.crawl.exception.NoTicketException;
import com.foreveross.taskservice.common.bean.TaskModel;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
/**
 * 西部航空
 * @author Administrator
 *
 */
public class WestAirAdapter extends AbstractAdapter {
	HttpClient client = null;
	private static int CRAW_COUNT=2;//回滚次数
	private static int WAITING_SECONDS=60000;//回滚等待时间
	public WestAirAdapter(TaskModel taskQueue) {
		super(taskQueue);
	}

	@Override
	public List<Object> paraseToVo(Object obj) throws Exception {
		switch (super.getRouteType()) {
		case INTERNATIONAL_ROUND:
			return null;// 国际往返
		case INTERNATIONAL_ONEWAY:
			return null;// 国际单程
		case DOMESTIC_ONEWAYTRIP:
			return paraseToVoS(obj);// 国内单程
		case DOMESTIC_ROUNDTRIP:
			return null;// 国内往返
		}
		return null;
	}
	
	/**
	 * 国内单程
	 */
	public List<Object> paraseToVoS(Object fetchObject) throws Exception {
		if(fetchObject==null){
			throw new Exception("没抓取到数据");
		}
		String tempResult = fetchObject.toString().trim();
		List<Object> list=new ArrayList<Object>();
		list = parseSourceDI(new Source(tempResult));

		tempResult = null;
		return list;
	}
	
	/**
	 * West——国内单程
	 */
	private List parseSourceDI(Source sources) throws Exception {
		List <AbstractPlaneInfoEntity> result = new ArrayList<AbstractPlaneInfoEntity>();
		try{
			Element formInfo=sources.getElementById("AirFlightItinerarySelectForm");//基础信息
			Element priceInfo=sources.getElementById("summaryBot_Left_airPrices");//价格信息
			Document doc=Jsoup.parse("<html><body>"+formInfo+"</body></html>");
			org.jsoup.nodes.Element div=doc.select("div.resultsArea").get(0);
			org.jsoup.select.Elements cabins=doc.select("span.ffTitle");//舱位商品名
			org.jsoup.select.Elements cabininfos=div.select("div.colPrice");
			
			org.jsoup.nodes.Element baseInfo=div.select("tbody").get(0);
			String flightNo=baseInfo.select("td.colFlight").text();
			String startTime=baseInfo.select("div.time").first().text();//出发程时间
			String endTime=baseInfo.select("div.time").get(1).text();//到达时间
			
			AbstractPlaneInfoEntity planeInfo = null;
			planeInfo = PlaneInfoEntityBuilder.buildPlaneInfo(taskQueue, "PN", "西部", "西部航空",startTime ,endTime,flightNo, null, null, null, null);
			//税收
			Double tax=0d;
			tax=Double.parseDouble(priceInfo.getAllElements("td").get(1).getTextExtractor().toString().split("\\ ")[1])+Double.parseDouble(priceInfo.getAllElements("td").get(2).getTextExtractor().toString().split("\\ ")[1]);
			List<String> priceList=new ArrayList<String>();
			//处理舱位信息
			if(cabins.size()>0 && cabininfos.size()>0){
				for(int i=0;i<cabins.size();i++){
					CabinEntity cabE=new CabinEntity(); 
					org.jsoup.nodes.Element cabinInfo=cabininfos.get(i);
					String price=null,name=null;
					price=cabinInfo.select("label").text();
					cabE.setCabinType(cabinInfo.select("div.toolTipInfo").select("div.toolTipSellingClass").text().split("\\ ")[1]);
					name=cabins.get(i).text();
					cabE.setPrice(price!=null?Double.parseDouble(price):0.0);
					cabE.setProductName(name);
					cabE.setTaxesPrice(tax);
					cabE.setOriginalPrice(tax+cabE.getPrice());
					priceList.add(price);
					PlaneInfoEntityBuilder.getSingleEntity(planeInfo).getCabins().add(cabE);
				}
				
			}
			
			if(priceList.size()>0){
				Collections.sort(priceList);
				planeInfo.setSumHighestPrice(tax+Double.parseDouble(priceList.get(priceList.size()-1)));
				planeInfo.setSumLowestPrice(tax+Double.parseDouble(priceList.get(0)));
				planeInfo.setTotalHighestPrice(Double.parseDouble(priceList.get(priceList.size()-1)));
				planeInfo.setTotalLowestPrice(Double.parseDouble(priceList.get(0)));
			}
			planeInfo.setTotalLowestTaxesPrice(tax);
			planeInfo.setTotalHighestTaxesPrice(tax);
			
			result.add(planeInfo);
			return result;
		}catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	
	
	//国内单程出发日期处理
	public String trDate(String dateStr,String timeStr){
		if(dateStr !=null && !dateStr.equals("") && timeStr !=null && !timeStr.equals("")){
			String dateStrs=null;
			dateStrs =dateStr+" "+timeStr+":00";
			return dateStrs;
		}
		
		return null;
	}
	
	
	
	
	public List<Object> paraseToVo_bak(Object fetchObject) throws Exception {
		if(fetchObject==null){
			throw new Exception("没抓取到数据");
		}
		List list = (List)fetchObject;
		if(list.size()==0){
			throw new Exception("没抓取到数据");
		}
		return list;
	}

	/**
	 * 国内单程
	 */
	@Override
	public String getUrl() throws Exception {
		StringBuffer url=new StringBuffer("http://www.westair.cn/InternetBooking/AirLowFareSearchExternal.do?airDate1=");
		url.append(taskQueue.getFlightDate())
		.append("&airDate2=")
		.append("&airplaneCity1=").append(URLEncoder.encode(taskQueue.getFromCityName(), "utf-8"))
		.append("&airplaneCity2=").append(URLEncoder.encode(taskQueue.getToCityName(), "utf-8"))
		.append("&coupon=")
		.append("&flexibleSearch=").append("false")
		.append("&guestTypes%5B0%5D.amount=1&guestTypes%5B0%5D.type=ADT&guestTypes%5B1%5D.amount=0&guestTypes%5B1%5D.type=CNN&guestTypes%5B2%5D.amount=0&guestTypes%5B2%5D.type=INF")
		.append("&inboundOption.departureDay=&inboundOption.departureMonth=&inboundOption.departureYear=")
		.append("&lang=").append("zh_CN")
		.append("&outboundOption.departureDay=").append(taskQueue.getFlightDate().substring(8,10))
		.append("&outboundOption.departureMonth=").append(taskQueue.getFlightDate().substring(5,7))
		.append("&outboundOption.departureYear=").append(taskQueue.getFlightDate().substring(0,4))
		.append("&outboundOption.destinationLocationCode=").append(taskQueue.getToCity())
		.append("&outboundOption.originLocationCode=").append(taskQueue.getFromCity())
		.append("&pos=WESTAIR_WEB").append("&reservationInput=").append("&tripType=").append("OW");
		return url.toString();
	}

	@Override
	public Object fetch(String url) throws Exception {
		return fetchFlight();
	}
	
	
	/**
	 * new version(新版本)
	 * 国内单程
	 * @return
	 * @throws Exception
	 */
	public Object fetchFlight() throws Exception{
		Object obj=null;
		WebClient webClient = this.getWebClientByFF();
		HtmlPage page=webClient.getPage(getUrl());
		webClient.waitForBackgroundJavaScriptStartingBefore(60000);
		page=webClient.getPage("http://www.westair.cn/InternetBooking/AirLowFareSearchExt.do?ajaxAction=true");
		webClient.waitForBackgroundJavaScriptStartingBefore(60000);
		page=webClient.getPage("http://www.westair.cn/InternetBooking/AirFareFamiliesFlexibleForward.do");
		obj=new Source(page.asXml());
		super.appendPageContents(page.asXml());//存入网页原数据
		super.setLenghtCount(page.asXml().length());//存入长度
		if(page.asXml().contains("您选择的日期找到空余可用的航班") || page.asXml().contains("其它可用的旅行日期")  || page.asXml().contains("无法根据您选择的日期找到空余可用的航班，请重新选择另一个日期")){
			throw new NoTicketException("该日期没有航班！");
		}
		
		/*if(page.asXml().contains("错误")){System.out.println(page.asXml());
			logger.info("抓取失败，回滚执行……");
			while(CRAW_COUNT-->0){
				Thread.sleep(WAITING_SECONDS);
				obj=fetchFlight();
			}
			
		}		
		if(page.asXml().contains("错误")){
			throw new MessageConstraintException("抓取失败！");
		}*/
		return obj ;
		
	}
	
	public List fetchFlight_bak() throws Exception{
		
		String flightDate = "flightDate="+taskQueue.getFlightDate();
		String returnDate = taskQueue.getIsReturn()==1?("returnDate="+taskQueue.getReturnGrabDate()):"";
		String tripType = taskQueue.getIsReturn()==1?"tripType=ROUNDTRIP":"tripType=ONEWAY";
		String url = "http://www.chinawestair.com/flight/searchflight.action?SDateType=FIXED&dstCity="+this.taskQueue.getToCity()+"&"+flightDate+"&orgCity="+this.taskQueue.getFromCity()+"&"+returnDate+"&"+tripType;
		client = this.getHttpClient();
		HttpPost request = new HttpPost(url);
		 
//		  HttpResponse ad = client.execute(request);
//		  HttpEntity entity = ad.getEntity();
//		  
//		 String data = EntityUtils.toString(entity,"GBK");
		 String data=super.excuteRequest(client, request, "GBK");
		 super.appendPageContents(data);
		 List<List<String>> hashFlight=RegHtmlUtil.retrieveLinkss(data, getRegex7());
		 for(List<String> list:hashFlight){
				String str=list.get(1);
				if(str.startsWith("很抱歉，没有符合条件的查询结果"))
					throw new FlightInfoNotFoundException(str);
		}
		 List<List<String>>list = RegHtmlUtil.retrieveLinkss(data, this.getRegex1());
		 if(list==null||list.size()==0){
			return new ArrayList();
		}
			List<AbstractPlaneInfoEntity> flights = getFlight(false,list.get(0));
			if(super.taskQueue.getIsReturn()!=1){ 
				return flights;
			}
			
			List returnFlights = getFlight(true,list.get(1));
			
			 for(AbstractPlaneInfoEntity from :flights){
				 PlaneInfoEntityBuilder.getDoubleEntity(from).getReturnPlaneInfos().addAll(returnFlights);
			 }
			 PlaneInfoEntityBuilder.buildRelation(flights, returnFlights);
			 PlaneInfoEntityBuilder.buildLimitPrice(flights);
			return flights;
	}
	
	public List<AbstractPlaneInfoEntity> getFlight(Boolean isReturn,List<String> flightsHtml) throws Exception{
		 List<String> cabinNames = RegHtmlUtil.retrieveLinks(flightsHtml.get(1), this.getRegex2(), 1);
		List<List<String>> flightsStr = RegHtmlUtil.retrieveLinkss(flightsHtml.get(2), this.getRegex3());
		if(flightsStr==null||flightsStr.size()==0){
			return new ArrayList<AbstractPlaneInfoEntity>();
		}
		
		List <AbstractPlaneInfoEntity> result = new ArrayList<AbstractPlaneInfoEntity>();
		List<List<String>> flightType=RegHtmlUtil.retrieveLinkss(flightsHtml.get(2), this.getRegex6());
		double taxesPrice=170;
		if(null!=flightType && flightType.size()>0){
			String taxesStr=flightType.get(0).get(1);
			if(null!=taxesStr && !"".equals(taxesStr)){
				String taxes[]=taxesStr.split("\\+");
				if(taxes.length>1){
					taxesPrice=PlaneInfoEntityBuilder.getDouble(taxes[0].replace(" ", ""))+
							PlaneInfoEntityBuilder.getDouble(taxes[1].replace(" ", ""));
				}
			}
		}
		for(List<String>flightStr:flightsStr){
			AbstractPlaneInfoEntity planeInfo = null;
			if(isReturn){
				planeInfo = PlaneInfoEntityBuilder.buildPlaneInfo(taskQueue, "PN", "西部", "西部航空",flightStr.get(2) , flightStr.get(3), flightStr.get(1), null, null, null, null,ReturnDoublePlaneInfoEntity.class);
			}else{
				planeInfo = PlaneInfoEntityBuilder.buildPlaneInfo(taskQueue, "PN", "西部", "西部航空",flightStr.get(2) , flightStr.get(3), flightStr.get(1), null, null, null, null);
			}
			List <String>cabinPriceTds = RegHtmlUtil.retrieveLinks(flightStr.get(5), getRegex4(), 1);
			for(int i=0;i<cabinPriceTds.size();i++){
				String td = cabinPriceTds.get(i);
				String price = RegHtmlUtil.regStr(td, getRegex5());
				if(StringUtils.isBlank(price)){
					continue;
				}
				this.buildCabin(isReturn, planeInfo, cabinNames.get(i), null, cabinNames.get(i), PlaneInfoEntityBuilder.getDouble(price),taxesPrice);
			}
			
			result.add(planeInfo);
		}
		
		if(null!=flightType && flightType.size()>0){
			if(flightType.size()==result.size()){
				for(int i=0;i<result.size();i++){
					result.get(i).setFlightType(flightType.get(i).get(2));
				}
			}
		}
		PlaneInfoEntityBuilder.buildLimitPrice(result);
		return result;
	}
		
	private void buildCabin(boolean isReturn,AbstractPlaneInfoEntity planeInfo,String cabinType,String subCabinName,String productName,Double price,Double taxesPrice){
		if(isReturn){
			ReturnCabinEntity cabinEntity = new ReturnCabinEntity();
			cabinEntity.setCabinType(cabinType);
			cabinEntity.setPlaneInfoEntity(planeInfo);
			cabinEntity.setPrice(price);
			cabinEntity.setProductName(productName);
			cabinEntity.setSubCabinName(subCabinName);
			PlaneInfoEntityBuilder.getReturnDoubleEntity(planeInfo).getReturnCabins().add(cabinEntity);
		}else{
			CabinEntity cabinEntity = new CabinEntity();
			cabinEntity.setCabinType(cabinType);
			cabinEntity.setPlaneInfoEntity(planeInfo);
			cabinEntity.setPrice(price);
			cabinEntity.setProductName(productName);
			cabinEntity.setSubCabinName(subCabinName);
			if(null==taxesPrice || taxesPrice==0){
				taxesPrice=170D;//国内税费默认为120+50
			}
			cabinEntity.setTaxesPrice(taxesPrice);
			cabinEntity.setOriginalPrice(price+taxesPrice);
			if(this.taskQueue.getIsReturn()==1){
				PlaneInfoEntityBuilder.getDoubleEntity(planeInfo).getCabins().add(cabinEntity);
			}else{
				PlaneInfoEntityBuilder.getSingleEntity(planeInfo).getCabins().add(cabinEntity);
			}
		}
		planeInfo.setTotalLowestPrice((planeInfo.getTotalLowestPrice()==null || 
				(planeInfo.getTotalLowestPrice()!=null && planeInfo.getTotalLowestPrice()>price)) ?
				price : planeInfo.getTotalLowestPrice());
		planeInfo.setTotalHighestPrice((planeInfo.getTotalHighestPrice()==null
				|| (planeInfo.getTotalHighestPrice()!=null && planeInfo.getTotalHighestPrice()<price)) ?
				price : planeInfo.getTotalHighestPrice());
	}

	
	
	@Override
	public boolean validateFetch(Object fetchObject) throws Exception {
		if(fetchObject == null){
			return false;
		}else if(StringUtils.isNotBlank(getSourceWebPageContents())){
			//验证字符串里是否包含抓取的错误信息
			if(fetchObject.toString().length() < 1000){
				throw new PageErrorResultException("抓取的数据不正确(长度少于1000)");
			}
		}
		return true;
	}
	
	/**
	 * 匹配没有航班
	 * @return
	 */
	public String getRegex7(){
		String regex ="<div id=\"flightDetailList\" class=\"b_fly_detail m_t_f1\" >\\s*?<br/><br/>(.+?)<br/><br/>";
		return regex;
	}
	
	public String getRegex1(){
		String regex = "<table[^\\r]+?class=\"tb_detail tb_detailtwo.*?\".+?<tr>\\s*?<th>.+?<th>.+?<th>.+?<th>.+?</th>(.+?)</tr>";//产品名称
		regex += "(.+?)</table>";//仓位信息
		return regex;
	}
	
	public String getRegex2(){
		String regex = "<th>(.+?)</th>";
		return regex;	
	}
	
	public String getRegex3(){
		String regex = "<tr>\\s+?<td>(.+?)</td>\\s*?";//航班
		regex += "<td>(.+?)</td>\\s*?<td>(.+?)</td>\\s*?";//开始日期 结束日期
		regex += "<td>(.+?)<.+?</td>(.+?)</tr>";//运营商名称
		return regex;
	}
	
	public String getRegex4(){
		String regex = "<td>(.+?)</td>";
		return regex;
	}
	
	public String getRegex5(){
		String regex = "<input.+?/>(.+)\\s*?";
		return regex;
	}
	
	//\u71c3\u6cb9\u8d39\uff1a 燃油费：
	//\u7ecf\u505c 经停
	//\u673a\u578b\uff1a 机型：
	public String getRegex6(){
		String regex="<tr>\\s+?<td>.+?</td>\\s+?<td>.+?</td>\\s+?<td>.+?</td>\\s+?<td.+?</tr>\\s+?<tr[^\\r].+?class=\"just_for_show_or_hide\">.+?";
		regex+="<p.+?<em.+?</em>.+?\u71c3\u6cb9\u8d39\uff1a(.+?)\u7ecf\u505c.+?\u673a\u578b\uff1a(.+?)</p>.+?</tr>"; //税费和飞机类型
		return regex;
	}

}
